home *** CD-ROM | disk | FTP | other *** search
- /*
- * fsPdevSetup.c --
- *
- * Open/Close/Migration routines for pseudo-devices.
- *
- * There are three kinds of streams involved in the implementation,
- * a "control" stream that is returned to the server when it first
- * opens the pseudo-device. When a client opens the pseudo-device
- * two streams are created and looked together. The "client" stream
- * is returned to the client process, and the "server" stream is
- * passed to the server process via the control stream.
- *
- * Copyright 1987, 1988 Regents of the University of California
- * Permission to use, copy, modify, and distribute this
- * software and its documentation for any purpose and without
- * fee is hereby granted, provided that the above copyright
- * notice appear in all copies. The University of California
- * makes no representations about the suitability of this
- * software for any purpose. It is provided "as is" without
- * express or implied warranty.
- */
-
- #ifndef lint
- static char rcsid[] = "$Header: /sprite/src/kernel/fspdev/RCS/fspdevSetup.c,v 9.6 91/06/26 01:05:40 mottsmth Exp $ SPRITE (Berkeley)";
- #endif not lint
-
- #include <sprite.h>
- #include <fs.h>
- #include <fsutil.h>
- #include <fsNameOps.h>
- #include <fsio.h>
- #include <fsconsist.h>
- #include <fsdm.h>
- #include <fsioLock.h>
- #include <proc.h>
- #include <rpc.h>
- #include <fspdevInt.h>
- #include <fspdev.h>
-
- /*
- *----------------------------------------------------------------------------
- *
- * FspdevNameOpen --
- *
- * Early open time processing, this is called on a fileserver
- * when setting up state for a call to the CltOpen routines on
- * the client host. For pseudo-device server processes, which
- * are indicated by the FS_PDEV_MASTER flag, check that no other
- * server exists. For all other processes, which are referred to
- * as "clients", make sure that a server process exists and
- * generate a new ioFileID for the connection between the client
- * and the server.
- *
- * Results:
- * For server processes, SUCCESS if it is now the server,
- * FS_FILE_BUSY if there already exists a server process. For
- * clients, SUCCESS if there is a server or the parameters
- * indicate this is only for get/set attributes, DEV_OFFLINE if
- * there is no server.
- *
- * Side effects:
- * Save the hostID of the calling process if
- * it is to be the server for the pseudo-device.
- *
- *----------------------------------------------------------------------------
- *
- */
- ReturnStatus
- FspdevNameOpen(handlePtr, openArgsPtr, openResultsPtr)
- register Fsio_FileIOHandle *handlePtr; /* A handle from FslclLookup.
- * Should be LOCKED upon entry,
- * unlocked upon exit. */
- Fs_OpenArgs *openArgsPtr; /* Standard open arguments */
- Fs_OpenResults *openResultsPtr;/* For returning ioFileID, streamID,
- * and Fsio_DeviceState */
- {
- register ReturnStatus status = SUCCESS;
- Fs_FileID ioFileID;
- register Fspdev_ControlIOHandle *ctrlHandlePtr;
- register Fs_Stream *streamPtr;
- register Fspdev_State *pdevStatePtr;
-
- /*
- * The control I/O handle is identified by the fileID of the pseudo-device
- * file with type CONTROL, and with the decriptor version number
- * xor'ed into the minor number to avoid conflict when you delete the
- * pdev file and recreate one with the same file number (minor field).
- */
- ioFileID = handlePtr->hdr.fileID;
- ioFileID.type = FSIO_CONTROL_STREAM;
- ioFileID.serverID = rpc_SpriteID;
- ioFileID.major = handlePtr->hdr.fileID.major;
- ioFileID.minor = handlePtr->hdr.fileID.minor ^
- (handlePtr->descPtr->version << 16);
- ctrlHandlePtr = FspdevControlHandleInit(&ioFileID, handlePtr->hdr.name);
-
- if (openArgsPtr->useFlags & FS_PDEV_MASTER) {
- /*
- * When a server opens we ensure there is only one.
- */
- if (ctrlHandlePtr->serverID != NIL) {
- status = FS_FILE_BUSY;
- } else {
- /*
- * Note which host is running the pseudo-device server.
- */
- ctrlHandlePtr->serverID = openArgsPtr->clientID;
- /*
- * Note our hostID is still in the hdr.serverID field of the
- * control handle being returned to the opening process. This is
- * used when closing the control stream to get back to us
- * so we can clear the serverID field here. We also set up
- * a shadow stream here, which has us as the server so
- * recovery and closing work right.
- */
- openResultsPtr->ioFileID = ioFileID;
- openResultsPtr->streamData = (ClientData)NIL;
- openResultsPtr->dataSize = 0;
- streamPtr = Fsio_StreamCreate(rpc_SpriteID, openArgsPtr->clientID,
- (Fs_HandleHeader *)ctrlHandlePtr,
- openArgsPtr->useFlags, handlePtr->hdr.name);
- openResultsPtr->streamID = streamPtr->hdr.fileID;
- Fsutil_HandleRelease(streamPtr, TRUE);
- }
- } else {
- if (openArgsPtr->useFlags == 0) {
- /*
- * Set up for get/set attributes. We point the client
- * at the name of the pseudo-device if it is not active,
- * otherwise we point it at the control stream handle that
- * has the current access and modify times.
- */
- if (ctrlHandlePtr->serverID == NIL) {
- openResultsPtr->ioFileID = handlePtr->hdr.fileID;
- } else {
- openResultsPtr->ioFileID = ctrlHandlePtr->rmt.hdr.fileID;
- if (openArgsPtr->clientID != ctrlHandlePtr->serverID) {
- /*
- * The requesting client is different than the pdev
- * server host. Unfortunately the serverID in the
- * control handle is us, the file server. We have
- * to hack the fileID so the client makes the RPC to
- * the pdev server. This relies on a parallel hack
- * in Fsrmt_GetIOAttr to fix up the serverID by
- * using the Fs_Attributes.serverID, which is us,
- * so that the correct control handle is found.
- */
- openResultsPtr->ioFileID.type = FSIO_RMT_CONTROL_STREAM;
- openResultsPtr->ioFileID.serverID = ctrlHandlePtr->serverID;
- }
- }
- } else if (ctrlHandlePtr->serverID == NIL) {
- /*
- * No server process.
- */
- status = DEV_OFFLINE;
- } else {
- /*
- * The server exists. Create a new I/O handle for the client.
- * The major and minor numbers are generated from the fileID
- * of the pseudo-device name (to avoid conflict with other
- * pseudo-devices) and a clone seed (to avoid conflict with
- * other clients of this pseudo-device).
- */
- if (ctrlHandlePtr->serverID == openArgsPtr->clientID) {
- openResultsPtr->ioFileID.type = FSIO_LCL_PSEUDO_STREAM;
- } else {
- openResultsPtr->ioFileID.type = FSIO_RMT_PSEUDO_STREAM;
- }
- openResultsPtr->ioFileID.serverID = ctrlHandlePtr->serverID;
- openResultsPtr->ioFileID.major =
- (handlePtr->hdr.fileID.serverID << 16) |
- handlePtr->hdr.fileID.major;
- ctrlHandlePtr->seed++;
- openResultsPtr->ioFileID.minor =
- ((handlePtr->descPtr->version << 24) ^
- (handlePtr->hdr.fileID.minor << 12)) |
- ctrlHandlePtr->seed;
- /*
- * Return the control stream file ID so it can be found again
- * later when setting up the client's stream and the
- * corresponding server stream. The procID and uid fields are
- * extra here, but will be used later if the client is remote.
- */
- pdevStatePtr = mnew(Fspdev_State);
- pdevStatePtr->ctrlFileID = ctrlHandlePtr->rmt.hdr.fileID;
- pdevStatePtr->procID = (Proc_PID)NIL;
- pdevStatePtr->uid = NIL;
- openResultsPtr->streamData = (ClientData)pdevStatePtr ;
- openResultsPtr->dataSize = sizeof(Fspdev_State);
- /*
- * Create a streamID for the opening process. No shadow
- * stream is kept here. Instead, the streamID is returned to
- * the pdev server who sets up the shadow stream.
- */
- Fsio_StreamCreateID(ctrlHandlePtr->serverID, &openResultsPtr->streamID);
- pdevStatePtr->streamID = openResultsPtr->streamID;
- }
- }
- Fsutil_HandleRelease(ctrlHandlePtr, TRUE);
- Fsutil_HandleUnlock(handlePtr);
- return(status);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * FspdevPseudoStreamIoOpen --
- *
- * This is called from Fs_Open, or from the RPC stub if the client
- * is remote, to complete setup of a client's
- * stream to the pseudo-device. The server is running on this
- * host. This routine creates a trivial client I/O handle
- * that references the server's I/O handle that has the main
- * state for the connection to the server. FspdevServerStreamCreate
- * is then called to set up the server's I/O handle, and the control
- * stream is used to pass a server stream to the server. Finally
- * an open transaction is made with the server process
- * to see if it will accept the client.
- *
- * Results:
- * SUCCESS, unless the server process has died recently, or the
- * server rejects the open.
- *
- * Side effects:
- * Creates the client's I/O handle. Calls FspdevServerStreamCreate
- * which sets up the servers corresponding I/O handle.
- *
- *----------------------------------------------------------------------
- */
-
- ReturnStatus
- FspdevPseudoStreamIoOpen(ioFileIDPtr, flagsPtr, clientID, streamData, name,
- ioHandlePtrPtr)
- register Fs_FileID *ioFileIDPtr; /* I/O fileID */
- int *flagsPtr; /* FS_READ | FS_WRITE ... */
- int clientID; /* Host doing the open */
- ClientData streamData; /* Pointer to Fspdev_State. */
- char *name; /* File name for error msgs */
- Fs_HandleHeader **ioHandlePtrPtr;/* Return - a locked handle set up for
- * I/O to a pseudo device, or NIL */
- {
- ReturnStatus status;
- Boolean foundStream;
- register Fspdev_ClientIOHandle *cltHandlePtr;
- register Fspdev_ControlIOHandle *ctrlHandlePtr;
- register Fspdev_State *pdevStatePtr;
- Fs_Stream *cltStreamPtr;
- Fs_Stream *srvStreamPtr;
- FspdevNotify *notifyPtr;
- Proc_ControlBlock *procPtr;
- Proc_PID procID;
- int uid;
-
- pdevStatePtr = (Fspdev_State *)streamData;
- ctrlHandlePtr = Fsutil_HandleFetchType(Fspdev_ControlIOHandle,
- &pdevStatePtr->ctrlFileID);
- /*
- * If there is no server present the creation of the stream
- * can't succeed. This case arises when the pseudo-device
- * master goes away between FspdevNameOpen and this call.
- */
- if ((ctrlHandlePtr == (Fspdev_ControlIOHandle *)NIL) ||
- (ctrlHandlePtr->serverID == NIL)) {
- status = DEV_OFFLINE;
- goto exit;
- }
-
- if (ctrlHandlePtr->rmt.hdr.fileID.serverID != rpc_SpriteID) {
- /*
- * Extract the seed from the minor field (see the SrvOpen routine).
- * This done in case of recovery when we'll need to reset the
- * seed kept on the file server.
- */
- ctrlHandlePtr->seed = ioFileIDPtr->minor & 0x0FFF;
- }
-
- cltHandlePtr = FspdevConnect(ctrlHandlePtr, ioFileIDPtr, clientID, 0);
- if (cltHandlePtr == (Fspdev_ClientIOHandle *)NIL) {
- status = DEV_OFFLINE;
- goto exit;
- }
- /*
- * Put the client on its own stream list.
- */
- cltStreamPtr = Fsio_StreamAddClient(&pdevStatePtr->streamID, clientID,
- (Fs_HandleHeader *)cltHandlePtr, *flagsPtr, name,
- (Boolean *)NIL, &foundStream);
- Fsutil_HandleRelease(cltStreamPtr, TRUE);
- Fsutil_HandleUnlock(cltHandlePtr);
- /*
- * Set up a stream for the server process. This will be picked
- * up by FspdevControlRead and converted to a user-level streamID.
- */
- srvStreamPtr = Fsio_StreamCreate(rpc_SpriteID, rpc_SpriteID,
- (Fs_HandleHeader *)cltHandlePtr->pdevHandlePtr,
- FS_READ|FS_USER, name);
- notifyPtr = mnew(FspdevNotify);
- notifyPtr->streamPtr = srvStreamPtr;
- List_InitElement((List_Links *)notifyPtr);
- List_Insert((List_Links *)notifyPtr,
- LIST_ATREAR(&ctrlHandlePtr->queueHdr));
- Fsutil_HandleUnlock(srvStreamPtr);
-
- Fsutil_FastWaitListNotify(&ctrlHandlePtr->readWaitList);
- Fsutil_HandleRelease(ctrlHandlePtr, TRUE);
- ctrlHandlePtr = (Fspdev_ControlIOHandle *)NIL;
- /*
- * Now that the request response stream is set up we do
- * our first transaction with the server process to see if it
- * will accept the open. We unlock the handle and rely on the
- * per-connection monitor lock instead. This is important because a
- * buggy pseudo-device server could be ignoring this connection
- * request indefinitely, and leaving handles locked for long periods
- * clogs up handle scavenging, and potentially recovery callbacks too.
- */
- if (clientID == rpc_SpriteID) {
- procPtr = Proc_GetEffectiveProc();
- procID = procPtr->processID;
- uid = procPtr->effectiveUserID;
- } else {
- procID = pdevStatePtr->procID;
- uid = pdevStatePtr->uid;
- }
- status = FspdevPseudoStreamOpen(cltHandlePtr->pdevHandlePtr, *flagsPtr,
- clientID, procID, uid);
- if (status == SUCCESS) {
- *ioHandlePtrPtr = (Fs_HandleHeader *)cltHandlePtr;
- } else {
- /*
- * Clean up client side, we assume server closes its half.
- */
- Fsutil_HandleInvalidate((Fs_HandleHeader *) cltHandlePtr);
- Fsutil_HandleRemove(cltHandlePtr);
- (void)Fsio_StreamClientClose(&cltStreamPtr->clientList, clientID);
- if (!foundStream) {
- /*
- * The client's stream wasn't already around from being installed
- * in Fs_Open, so we nuke the shadow stream we've created.
- */
- cltStreamPtr = Fsutil_HandleFetchType(Fs_Stream,
- &cltStreamPtr->hdr.fileID);
- Fsio_StreamDestroy(cltStreamPtr);
- }
- }
- exit:
- if (ctrlHandlePtr != (Fspdev_ControlIOHandle *)NIL) {
- Fsutil_HandleRelease(ctrlHandlePtr, TRUE);
- }
- free((Address)streamData);
- return(status);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * FspdevConnect --
- *
- * This sets up a pseduo-device connection. This is called from
- * the PseudoStreamCltOpen routine with ordinary pseudo-devices,
- * and from FspdevPfsIoOpen to set up the naming connection to a
- * pseudo-filesystem server, and during an IOC_PFS_OPEN by a
- * pseudo-filesystem server to set up a connection to a client.
- * The case of the naming stream is distinguished by the last
- * parameter. The state of this needs to be marked specially
- * so proper clean up can be made later.
- *
- * Results:
- * A pointer to a Fspdev_ClientIOHandle that references a Fspdev_ServerIOHandle.
- * The client handle is returned locked, but the server handle it
- * references is not locked.
- *
- * Side effects:
- * Creates the client's I/O handle. Calls FspdevServerStreamCreate
- * which sets up the servers corresponding I/O handle.
- * This changes the ioFileIDPtr->type from FSIO_LCL_PSEUDO_STREAM to
- * FSIO_SERVER_STREAM.
- *
- *----------------------------------------------------------------------
- */
-
- Fspdev_ClientIOHandle *
- FspdevConnect(ctrlHandlePtr, ioFileIDPtr, clientID, naming)
- Fspdev_ControlIOHandle *ctrlHandlePtr; /* Control stream handle */
- register Fs_FileID *ioFileIDPtr; /* I/O fileID */
- int clientID; /* Host ID of client-side */
- Boolean naming; /* TRUE if called from FspdevPfsIoOpen
- * to set up the naming stream */
- {
- Boolean found;
- Fs_HandleHeader *hdrPtr;
- register Fspdev_ClientIOHandle *cltHandlePtr;
-
- found = Fsutil_HandleInstall(ioFileIDPtr, sizeof(Fspdev_ClientIOHandle),
- ctrlHandlePtr->rmt.hdr.name, FALSE, &hdrPtr);
- cltHandlePtr = (Fspdev_ClientIOHandle *)hdrPtr;
- if (found) {
- if ((cltHandlePtr->pdevHandlePtr != (Fspdev_ServerIOHandle *)NIL) &&
- (cltHandlePtr->pdevHandlePtr->clientPID != (unsigned int)NIL)) {
- printf(
- "FspdevConnect found client handle\n");
- printf("Check (and kill) client process %x\n",
- cltHandlePtr->pdevHandlePtr->clientPID);
- }
- /*
- * Invalidate this lingering handle. The client process is hung
- * or suspended and hasn't closed its end of the pdev connection.
- */
- Fsutil_HandleInvalidate((Fs_HandleHeader *)cltHandlePtr);
- Fsutil_HandleRelease(cltHandlePtr, TRUE);
-
- found = Fsutil_HandleInstall(ioFileIDPtr, sizeof(Fspdev_ClientIOHandle),
- ctrlHandlePtr->rmt.hdr.name, FALSE, &hdrPtr);
- cltHandlePtr = (Fspdev_ClientIOHandle *)hdrPtr;
- if (found) {
- panic( "FspdevConnect handle still there\n");
- }
- }
- /*
- * Set up the connection state and hook the client handle to it.
- */
- cltHandlePtr->pdevHandlePtr = FspdevServerStreamCreate(ioFileIDPtr,
- ctrlHandlePtr->rmt.hdr.name, naming);
- if (cltHandlePtr->pdevHandlePtr == (Fspdev_ServerIOHandle *)NIL) {
- Fsutil_HandleRemove(cltHandlePtr);
- return((Fspdev_ClientIOHandle *)NIL);
- }
- cltHandlePtr->pdevHandlePtr->ctrlHandlePtr = ctrlHandlePtr;
- cltHandlePtr->segPtr = (struct Vm_Segment *)NIL; /* JMS */
- /*
- * Set up the client list in case the client is remote.
- */
- List_Init(&cltHandlePtr->clientList);
- (void)Fsconsist_IOClientOpen(&cltHandlePtr->clientList, clientID, 0, FALSE);
- /*
- * Grab an extra reference to the server's handle so the
- * server close routine can remove the handle and it won't
- * go away until the client also closes.
- */
- Fsutil_HandleUnlock(cltHandlePtr->pdevHandlePtr);
- (void)Fsutil_HandleDup((Fs_HandleHeader *)cltHandlePtr->pdevHandlePtr);
- Fsutil_HandleUnlock(cltHandlePtr->pdevHandlePtr);
-
- return(cltHandlePtr);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * FspdevRmtPseudoStreamIoOpen --
- *
- * Complete a remote client's stream to a pseudo-device.
- * The client is on a different host than the server process. This
- * makes an RPC to the pseudo-device server's host to invoke
- * FspdevPseudoStreamIoOpen, which sets up the pdev connection.
- * This host only keeps a Fsrmt_IOHandle that implicitly references
- * the pdev connection on the pdev server's host.
- *
- * Results:
- * SUCCESS unless the server process has died recently, then DEV_OFFLINE.
- *
- * Side effects:
- * RPC to the server's host to invoke the regular setup routines.
- *
- *----------------------------------------------------------------------
- */
- /*ARGSUSED*/
- ReturnStatus
- FspdevRmtPseudoStreamIoOpen(ioFileIDPtr, flagsPtr, clientID, streamData, name,
- ioHandlePtrPtr)
- register Fs_FileID *ioFileIDPtr; /* I/O fileID */
- int *flagsPtr; /* FS_READ | FS_WRITE ... */
- int clientID; /* IGNORED (== rpc_SpriteID) */
- ClientData streamData; /* NIL for us. */
- char *name; /* File name for error msgs */
- Fs_HandleHeader **ioHandlePtrPtr;/* Return - a locked handle set up for
- * I/O to a pseudo device, or NIL */
- {
- register ReturnStatus status;
- register Proc_ControlBlock *procPtr;
- register Fspdev_State *pdevStatePtr = (Fspdev_State *)streamData;
-
- /*
- * Use RPC to invoke FspdevPseudoStreamIoOpen which sets up the connection.
- */
- procPtr = Proc_GetEffectiveProc();
- pdevStatePtr->procID = procPtr->processID;
- pdevStatePtr->uid = procPtr->effectiveUserID;
- ioFileIDPtr->type = FSIO_LCL_PSEUDO_STREAM;
- status = Fsrmt_DeviceOpen(ioFileIDPtr, *flagsPtr, sizeof(Fspdev_State),
- (ClientData)pdevStatePtr);
- if (status == SUCCESS) {
- ioFileIDPtr->type = FSIO_RMT_PSEUDO_STREAM;
- Fsrmt_IOHandleInit(ioFileIDPtr, *flagsPtr, name, ioHandlePtrPtr);
- }
- free((Address)pdevStatePtr);
- return(status);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * FspdevPseudoStreamClose --
- *
- * Close a pseudo stream that's been used by a client to talk to a server.
- * This issues a close message to the server and then tears down the
- * state used to implement the pseudo stream connection.
- *
- * Results:
- * SUCCESS.
- *
- * Side effects:
- * Other than the request-response to the server, this releases the
- * pseudo stream's reference to the handle. This may also have
- * to contact a remote host to clean up references there, too.
- *
- *----------------------------------------------------------------------
- */
- /*ARGSUSED*/
- #ifndef SOSP91
- ReturnStatus
- FspdevPseudoStreamClose(streamPtr, clientID, procID, flags, size, data)
- #else
- ReturnStatus
- FspdevPseudoStreamClose(streamPtr, clientID, procID, flags, size, data,
- offsetPtr, rwFlagsPtr)
- #endif
- Fs_Stream *streamPtr; /* Client pseudo-stream to close */
- int clientID; /* HostID of client closing */
- Proc_PID procID; /* ID of closing process, IGNORED */
- int flags; /* IGNORED */
- int size; /* Should be zero */
- ClientData data; /* IGNORED */
- #ifdef SOSP91
- int *offsetPtr;
- int *rwFlagsPtr;
- #endif
- {
- register Fspdev_ClientIOHandle *cltHandlePtr =
- (Fspdev_ClientIOHandle *)streamPtr->ioHandlePtr;
- Boolean cache = FALSE;
-
- DBG_PRINT( ("Client closing pdev %x,%x\n",
- cltHandlePtr->hdr.fileID.major,
- cltHandlePtr->hdr.fileID.minor) );
-
- if (!Fsconsist_IOClientClose(&cltHandlePtr->clientList, clientID, 0, &cache)) {
- /*
- * Invalid client trying to close.
- */
- printf( "FspdevPseudoStreamClose: client %d not found\n",
- clientID);
- Fsutil_HandleUnlock(cltHandlePtr);
- return(GEN_INVALID_ARG);
- } else if (!List_IsEmpty(&cltHandlePtr->clientList)) {
- /*
- * Still clients out there.
- */
- Fsutil_HandleUnlock(cltHandlePtr);
- } else {
- /*
- * No clients remaining so we can close down the connection.
- * Notify the server that a client has gone away. Then we get rid
- * of our reference to the server's handle and nuke our own.
- * Note we unlock the client handle before the request response
- * in case the server process is buggy and hangs us.
- */
- Fsutil_HandleUnlock(cltHandlePtr);
- FspdevPseudoStreamCloseInt(cltHandlePtr->pdevHandlePtr);
- Fsutil_HandleRelease(cltHandlePtr->pdevHandlePtr, FALSE);
- Fsutil_HandleRelease(cltHandlePtr, FALSE);
- Fsutil_HandleRemove(cltHandlePtr);
- }
- return(SUCCESS);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * FspdevPseudoStreamMigClose --
- *
- * Called to release a reference on a pseudo stream. However, there
- * is always only one refernece on the handle so we do nothing.
- *
- * Results:
- * SUCCESS.
- *
- * Side effects:
- * Release the I/O handle.
- *
- *----------------------------------------------------------------------
- */
- /*ARGSUSED*/
- ReturnStatus
- FspdevPseudoStreamMigClose(hdrPtr, flags)
- Fs_HandleHeader *hdrPtr; /* File being encapsulated */
- int flags; /* Use flags from the stream */
- {
- panic( "FspdevPseudoStreamMigClose called\n");
-
- return(SUCCESS);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * FspdevPseudoStreamMigrate --
- *
- * Migrate a pseudo-stream client.
- *
- * This takes care of transfering references from one client to the other.
- * A useful side-effect of this routine is to properly set the type in
- * the ioFileID, either FSIO_LCL_PSEUDO_STREAM or FSIO_RMT_PSEUDO_STREAM.
- * In the latter case FspdevRmtPseudoStreamMigrate is called to do all
- * the work.
- *
- * Results:
- * An error status if the I/O handle can't be set-up.
- * Otherwise SUCCESS is returned, *flagsPtr may have the FS_RMT_SHARED
- * bit set, and *sizePtr and *dataPtr are set to reference Fspdev_State.
- *
- * Side effects:
- * Sets the correct stream type on the ioFileID.
- * Shifts client references from the srcClient to the destClient.
- * Set up and return Fspdev_State for use by the MigEnd routine.
-
- *
- *----------------------------------------------------------------------
- */
- /*ARGSUSED*/
- ReturnStatus
- FspdevPseudoStreamMigrate(migInfoPtr, dstClientID, flagsPtr, offsetPtr, sizePtr,
- dataPtr)
- Fsio_MigInfo *migInfoPtr; /* Migration state */
- int dstClientID; /* ID of target client */
- int *flagsPtr; /* In/Out Stream usage flags */
- int *offsetPtr; /* Return - new stream offset */
- int *sizePtr; /* Return - sizeof(Fspdev_State) */
- Address *dataPtr; /* Return - pointer to Fspdev_State */
- {
- Fspdev_ClientIOHandle *cltHandlePtr;
- Boolean closeSrcClient;
-
- if (migInfoPtr->ioFileID.serverID != rpc_SpriteID) {
- /*
- * The device was local, which is why we were called, but is
- * now remote.
- */
- migInfoPtr->ioFileID.type = FSIO_RMT_PSEUDO_STREAM;
- return(FspdevRmtPseudoStreamMigrate(migInfoPtr, dstClientID, flagsPtr,
- offsetPtr, sizePtr, dataPtr));
- }
- migInfoPtr->ioFileID.type = FSIO_LCL_PSEUDO_STREAM;
- cltHandlePtr = Fsutil_HandleFetchType(Fspdev_ClientIOHandle, &migInfoPtr->ioFileID);
- if (cltHandlePtr == (Fspdev_ClientIOHandle *)NIL) {
- panic( "FspdevPseudoStreamMigrate, no client handle <%d,%x,%x>\n",
- migInfoPtr->ioFileID.serverID,
- migInfoPtr->ioFileID.major, migInfoPtr->ioFileID.minor);
- return(FAILURE);
- }
- DBG_PRINT( ("Migrating pdev %x,%x, ref %d.\n",
- cltHandlePtr->hdr.fileID.major,
- cltHandlePtr->hdr.fileID.minor,
- cltHandlePtr->hdr.refCount) );
- /*
- * At the stream level, add the new client to the set of clients
- * for the stream, and check for any cross-network stream sharing.
- */
- Fsio_StreamMigClient(migInfoPtr, dstClientID, (Fs_HandleHeader *)cltHandlePtr,
- &closeSrcClient);
-
- /*
- * Move the client at the I/O handle level. The flags are used
- * by FsIOClient{Open,Close} and are different for pdevs than
- * other files -- namely, the flags are set to 0 before calls to these
- * routines. The only flag we have to make sure to pass is
- * whether it's a new stream, since this is used by Fsio_MigrateClient
- * itself.
- */
- Fsio_MigrateClient(&cltHandlePtr->clientList, migInfoPtr->srcClientID,
- dstClientID, (int)(migInfoPtr->flags & FS_NEW_STREAM),
- closeSrcClient);
-
- *sizePtr = 0;
- *dataPtr = (Address)NIL;
- *flagsPtr = migInfoPtr->flags;
- *offsetPtr = migInfoPtr->offset;
- /*
- * We don't need this reference on the I/O handle; there is no change.
- */
- Fsutil_HandleRelease(cltHandlePtr, TRUE);
- return(SUCCESS);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * FspdevRmtPseudoStreamMigrate --
- *
- * Migrate a pseudo-stream client.
- * This takes care of transfering references from one client to the other.
- * A useful side-effect of this routine is to properly set the type in
- * the ioFileID, either FSIO_LCL_PSEUDO_STREAM or FSIO_RMT_PSEUDO_STREAM.
- * In the former case FspdevPseudoStreamMigrate is called to do all the work.
- *
- * Results:
- * An error status if the I/O handle can't be set-up.
- * Otherwise SUCCESS is returned, *flagsPtr may have the FS_RMT_SHARED
- * bit set, and *sizePtr and *dataPtr are set to reference Fspdev_State.
- *
- * Side effects:
- * Sets the correct stream type on the ioFileID.
- * Shifts client references from the srcClient to the destClient.
- *
- *----------------------------------------------------------------------
- */
- /*ARGSUSED*/
- ReturnStatus
- FspdevRmtPseudoStreamMigrate(migInfoPtr, dstClientID, flagsPtr, offsetPtr,
- sizePtr, dataPtr)
- Fsio_MigInfo *migInfoPtr; /* Migration state */
- int dstClientID; /* ID of target client */
- int *flagsPtr; /* In/Out Stream usage flags */
- int *offsetPtr; /* Return - the new stream offset */
- int *sizePtr; /* Return - 0 */
- Address *dataPtr; /* Return - NIL */
- {
- register ReturnStatus status;
-
- if (migInfoPtr->ioFileID.serverID == rpc_SpriteID) {
- /*
- * The device was remote, which is why we were called, but is now local.
- */
- migInfoPtr->ioFileID.type = FSIO_LCL_PSEUDO_STREAM;
- return(FspdevPseudoStreamMigrate(migInfoPtr, dstClientID, flagsPtr,
- offsetPtr, sizePtr, dataPtr));
- }
- migInfoPtr->ioFileID.type = FSIO_RMT_PSEUDO_STREAM;
- status = Fsrmt_NotifyOfMigration(migInfoPtr, flagsPtr, offsetPtr,
- 0, (Address)NIL);
- DBG_PRINT( ("Migrating remote pdev %x,%x.\n",
- migInfoPtr->ioFileID.major,
- migInfoPtr->ioFileID.minor) );
- if (status != SUCCESS) {
- printf( "FsrmtDeviceMigrate, server error <%x>\n",
- status);
- } else {
- *dataPtr = (Address)NIL;
- *sizePtr = 0;
- }
- return(status);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * FspdevPseudoStreamMigOpen --
- *
- * Complete setup of a pdev client I/O handle after migrating a stream
- * to the I/O server of the pseudo-device connection (the host running
- * the user-level server process). FspdevPseudoStreamMigrate has done
- * the work of shifting use counts at the stream and I/O handle level.
- * This routine fills in the stream's ioHandlePtr, but doens't adjust
- * the low-level reference count on the I/O handle (like other MigEnd
- * procedures) because the reference count isn't used the same way.
- * With pseudo-device connections, there is always only one refCount
- * on the client handle, but there may be entries in the clientList
- * to reflect remote clients.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
- /*ARGSUSED*/
- ReturnStatus
- FspdevPseudoStreamMigOpen(migInfoPtr, size, data, hdrPtrPtr)
- Fsio_MigInfo *migInfoPtr; /* Migration state */
- int size; /* Zero */
- ClientData data; /* NIL */
- Fs_HandleHeader **hdrPtrPtr; /* Return - handle for the file */
- {
- register Fspdev_ClientIOHandle *cltHandlePtr;
-
- cltHandlePtr = Fsutil_HandleFetchType(Fspdev_ClientIOHandle,
- &migInfoPtr->ioFileID);
- if (cltHandlePtr == (Fspdev_ClientIOHandle *)NIL) {
- panic( "FspdevPseudoStreamMigOpen, no handle.\n");
- return(FAILURE);
- } else {
- /*
- * Release this reference so the client handle always has
- * just one reference. Instead of refcounts, an empty
- * client list indicates there are no more clients.
- */
- Fsutil_HandleRelease(cltHandlePtr, TRUE);
- *hdrPtrPtr = (Fs_HandleHeader *)cltHandlePtr;
- return(SUCCESS);
- }
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * FspdevRmtPseudoStreamVerify --
- *
- * Verify that the remote client is known for the pdev, and return
- * a locked pointer to the client I/O handle.
- *
- * Results:
- * A pointer to the client I/O handle, or NIL if
- * the client is bad.
- *
- * Side effects:
- * The handle is returned locked and with its refCount incremented.
- * It should be released with Fsutil_HandleRelease.
- *
- *----------------------------------------------------------------------
- */
-
- Fs_HandleHeader *
- FspdevRmtPseudoStreamVerify(fileIDPtr, clientID, domainTypePtr)
- Fs_FileID *fileIDPtr; /* Client's I/O file ID */
- int clientID; /* Host ID of the client */
- int *domainTypePtr; /* Return - FS_PSEUDO_DOMAIN */
- {
- register Fspdev_ClientIOHandle *cltHandlePtr;
- register Fsconsist_ClientInfo *clientPtr;
- Boolean found = FALSE;
-
- if (fileIDPtr->type > 0 && fileIDPtr->type < FSIO_NUM_STREAM_TYPES) {
- fileIDPtr->type = fsio_RmtToLclType[fileIDPtr->type];
- }
- if (fileIDPtr->type != FSIO_LCL_PSEUDO_STREAM &&
- fileIDPtr->type != FSIO_LCL_PFS_STREAM) {
- printf( "FspdevRmtPseudoStreamVerify, bad type <%d>\n",
- fileIDPtr->type);
- return((Fs_HandleHeader *)NIL);
- }
- cltHandlePtr = Fsutil_HandleFetchType(Fspdev_ClientIOHandle, fileIDPtr);
- if (cltHandlePtr != (Fspdev_ClientIOHandle *)NIL) {
- LIST_FORALL(&cltHandlePtr->clientList, (List_Links *) clientPtr) {
- if (clientPtr->clientID == clientID) {
- found = TRUE;
- break;
- }
- }
- if (!found) {
- Fsutil_HandleRelease(cltHandlePtr, TRUE);
- cltHandlePtr = (Fspdev_ClientIOHandle *)NIL;
- }
- }
- if (!found) {
- printf(
- "FspdevRmtPseudoStreamVerify, client %d not known for %s <%x,%x>\n",
- clientID, Fsutil_FileTypeToString(fileIDPtr->type),
- fileIDPtr->major, fileIDPtr->minor);
- }
- if (domainTypePtr != (int *)NIL) {
- *domainTypePtr = FS_PSEUDO_DOMAIN;
- }
- return((Fs_HandleHeader *)cltHandlePtr);
- }
-